<template>
  <div class="captcha-container">
    <a-spin :spinning="loading" class="margin-top-sm"/>
    <canvas v-show="!loading" ref="captchaCanvas" class="captcha-canvas" @click="generateCaptcha"/>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
// 定义响应式数据
const captchaCanvas = ref<HTMLCanvasElement | null>(null)
const captchaCode = defineModel<string>('code')
const loading = ref<boolean>(false)
// 验证码配置
const captchaConfig = {
  width: 120,
  height: 40,
  codeLength: 4,
  backgroundColor: '#fff'
}

// 生成随机字符
const generateRandomCode = (): string => {
  const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let code = ''
  for (let i = 0; i < captchaConfig.codeLength; i++) {
    code += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  return code
}

// 绘制验证码
const drawCaptcha = () => {
  if (!captchaCanvas.value) return
  
  const canvas = captchaCanvas.value
  const ctx = canvas.getContext('2d')
  if (!ctx) return
  
  // 设置画布尺寸
  canvas.width = captchaConfig.width
  canvas.height = captchaConfig.height
  
  // 绘制背景
  ctx.fillStyle = captchaConfig.backgroundColor
  ctx.fillRect(0, 0, captchaConfig.width, captchaConfig.height)
  
  // 绘制验证码文本
  ctx.font = '20px Arial'
  ctx.textBaseline = 'middle'
  
  const code = captchaCode.value as string
  const xSpacing = captchaConfig.width / (code.length + 1)
  
  for (let i = 0; i < code.length; i++) {
    // 随机颜色
    ctx.fillStyle = `rgb(${Math.floor(Math.random() * 150)}, ${Math.floor(Math.random() * 150)}, ${Math.floor(Math.random() * 150)})`
    
    // 随机位置和旋转
    const x = xSpacing * (i + 1)
    const y = captchaConfig.height / 2
    const angle = (Math.random() * 0.4 - 0.2) * Math.PI
    
    ctx.save()
    ctx.translate(x, y)
    ctx.rotate(angle)
    ctx.fillText(code.charAt(i), 0, 0)
    ctx.restore()
  }
  
  // 绘制干扰线
  for (let i = 0; i < 5; i++) {
    ctx.strokeStyle = `rgb(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)})`
    ctx.beginPath()
    ctx.moveTo(Math.random() * captchaConfig.width, Math.random() * captchaConfig.height)
    ctx.lineTo(Math.random() * captchaConfig.width, Math.random() * captchaConfig.height)
    ctx.stroke()
  }
  
  // 绘制干扰点
  for (let i = 0; i < 30; i++) {
    ctx.fillStyle = `rgb(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)})`
    ctx.beginPath()
    ctx.arc(
      Math.random() * captchaConfig.width,
      Math.random() * captchaConfig.height,
      Math.random() * 2,
      0,
      Math.PI * 2
    )
    ctx.fill()
  }
}

// 生成新的验证码
const generateCaptcha = () => {
  captchaCode.value = generateRandomCode()
  loading.value = true
  setTimeout(() => {
    drawCaptcha()
    loading.value = false
  },500)
}

// 验证输入的验证码
const validateCaptcha = (code:string): boolean => {
  return code.toUpperCase() === captchaCode.value?.toUpperCase()
}

// 组件挂载后生成验证码
onMounted(() => {
  generateCaptcha()
})

// 暴露给父组件的方法
defineExpose({
  validateCaptcha,
  refreshCaptcha: generateCaptcha,
  captchaCode: captchaCode
})
</script>

<style scoped>
.captcha-container {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

.captcha-canvas {
  cursor: pointer;
  background-color: #f0f0f0;
}
</style>